package connect

import (
	"encoding/json"
	"github.com/gorilla/websocket"
	_ "net/http/pprof"
)

type Server struct {
	room       *Room
	userGroup  *UserGroup
	conn2User  map[*websocket.Conn]*User
	msgHandler map[string]func(conn *websocket.Conn, msg *MessageFromUser)
}

func NewServer() *Server {
	server := &Server{
		room:       NewRoom(),
		userGroup:  NewUserGroup(),
		conn2User:  make(map[*websocket.Conn]*User),
		msgHandler: make(map[string]func(conn *websocket.Conn, msg *MessageFromUser)),
	}

	return server
}

func (server *Server) RegisterMsgHandler(types string, handler func(conn *websocket.Conn, msg *MessageFromUser)) {
	server.msgHandler[types] = handler
}

// 连接处理
func (server *Server) HandlerConnect(conn *websocket.Conn, broadcast chan []byte) {
	// 创建用户
	user := NewUser(conn, broadcast)
	server.userGroup.Add(user)
	server.conn2User[conn] = user
}

// 连接关闭处理
func (server *Server) HandlerDisConnect(conn *websocket.Conn) {
	user, ok := server.conn2User[conn]
	if !ok {
		return
	}

	userId := user.UserId
	delete(server.conn2User, conn)

	server.userGroup.Del(userId)
	server.room.DelUser(user)
}

func (server *Server) HandlerRead(conn *websocket.Conn, message []byte) {
	_, ok := server.conn2User[conn]
	if !ok {
		return
	}

	msgStr := &MessageFromUser{}
	err := json.Unmarshal(message, msgStr)
	if err != nil {
		return
	}

	if handler, ok := server.msgHandler[msgStr.To["type"].(string)]; ok {
		handler(conn, msgStr)
	}
}

// 初始化处理
func (server *Server) HandlerMsgInit(conn *websocket.Conn, msg *MessageFromUser) {
	user := server.conn2User[conn]
	user.UserName = msg.Mine.UserName

	// 推送初始化消息给用户
	user.broadcast <- NewMessageInitSuccess(user.UserId).GetData()

	// 添加到默认房间
	server.room.AddUser(user)
}

// 群消息处理
func (server *Server) HandlerMsgGroup(conn *websocket.Conn, msg *MessageFromUser) {
	user := server.conn2User[conn]

	// 群消息
	message := &MessageText{
		UserName:  msg.Mine.UserName,
		Avatar:    msg.Mine.Avatar,
		GroupId:   server.room.roomId,
		Type:      "group",
		Content:   msg.Mine.Content,
		Cid:       0,
		Mine:      false,
		FormId:    msg.Mine.Id,
		TimeStamp: msg.Mine.Timestamp,
	}

	server.room.Push(user, message)
}
